#include "include/lhmodbuslib.h"
#include "include/mymodbus.h"
#include "include/parammodbus.h"
#include "qjsonarray.h"
#include "qjsondocument.h"
#include "qjsonobject.h"
#include "qjsonvalue.h"
#include <QCoreApplication>
#include <QDebug>
#include <QFileInfo>
#include <QSettings>
#include <QTextCodec>
#include <QTimer>
#include <QtMath>
MyModbus* myModbus;
LHModbusLib::LHModbusLib( QObject* parent ) {
    qRegisterMetaType< QModbusDataUnit >( "QModbusDataUnit" );
    qRegisterMetaType< QModbusDataUnit >( "QModbusDataUnit&" );
    QFileInfo file( "./" );
    qDebug() << "LHModbusLib readParam" << file.absolutePath();
    qDebug() << "init LHModbusLib";
    ParamModbus::readModbusParam();
    ParamModbus::printModbusParam();
    qDebug() << "LHModbusLib readParam " << ParamModbus::SerialPortNameParameter;
    ModbusRWParam::getInstance().readReadWiter();
    writerList         = new QList< QModbusDataUnit >();
    writerListCache    = new QMap< QString, QModbusDataUnit >();
    hightFreqenceyUnit = onInitModbusDataUnit( "hight_freqencey" );
}

LHModbusLib::~LHModbusLib() {
    if ( writerList && !writerList->isEmpty() ) delete writerList;
    if ( myModbus ) { delete myModbus; }
    qDebug() << "~LHModbusLib";
}

void LHModbusLib::onModbusIntWriter( const QString& key, int data ) {
    if ( isError || writerList->size() > ParamModbus::WriterMaxSize ) { return; }
    if ( writerListCache->contains( key ) && onWriterIsSame( key, data ) ) {
        qDebug() << "int same";
        return;
    }
    QModbusDataUnit init = onInitModbusDataUnit( key );
    if ( init.registerType() != QModbusDataUnit::RegisterType::Invalid ) {
        init.setValue( 0, static_cast< quint16 >( data ) );
        writerListCache->insert( key, init );
        writerList->append( init );
    }
    else {
        qDebug() << "Writer int 表不存在该 key ->" << key;
    }
}

void LHModbusLib::onModbusStringWriter( const QString& key, const QString data ) {
    if ( isError || writerList->size() > ParamModbus::WriterMaxSize ) { return; }
    if ( writerListCache->contains( key ) && onWriterIsSame( key, data ) ) {
        qDebug() << "String same";
        return;
    }
    QModbusDataUnit init = onInitModbusDataUnit( key );
    if ( init.registerType() != QModbusDataUnit::RegisterType::Invalid ) {
        onConfigWriterString( init, data );
        writerListCache->insert( key, init );
        writerList->append( init );
    }
    else {
        qDebug() << "Writer string 表不存在该 key ->" << key;
    }
}

void LHModbusLib::onModbusListWriter( const QString& key, bool isClear, const QStringList data ) {
    if ( isError || writerList->size() > ParamModbus::WriterMaxSize ) { return; }
    ModbusRWParam::ModbusListIniMode initListMode;
    if ( ModbusRWParam::getInstance().getWriterModbusListIniMode( key, initListMode ) ) {
        if ( isClear ) {
            QModbusDataUnit controlUnit = QModbusDataUnit( QModbusDataUnit::RegisterType::HoldingRegisters, initListMode.control_adress, 1 );
            controlUnit.setValue( 0, initListMode.control_clear_now_value );
            writerList->append( controlUnit );
        }
        if ( data.size() > 1 ) {
            for ( int i = 0; i < data.size(); i++ ) {
                onConfigWriterListInter( data.at( i ), initListMode );
            }
        }
    }
    else {
        qDebug() << "Writer list string 表不存在该 key ->" << key;
    }
}

void LHModbusLib::onModbusHighFrequencyWriter( const QString& key, int data ) {
    if ( isError ) return;
    int index;
    if ( ModbusRWParam::getInstance().getWriterModbusIntHighFrequencey( key, index ) ) { hightFreqenceyUnit.setValue( index, static_cast< quint16 >( data ) ); }
    else {
        qDebug() << "ModbusHighFrequencyWriter 不存在该配置 key:" << key;
    }
}
/**
 * @brief LHModbusLib::slotModbusReadBack
 * @param readData
 * qt modbus读功能返回的结果
 */
void LHModbusLib::slotModbusReadBack( const QModbusDataUnit readData ) {
    if ( isError ) isError = false;
    QString key            = ModbusRWParam::getInstance().getReadKeyByAddress( readData.startAddress() );
    if ( key == "" ) {
        qDebug() << "ModbusRead.ini 不存在该地址的key";
        key = QString( readData.startAddress() );
    }
    emit signalsModbusBack( key, readData, "" );
}
/**
 * @brief LHModbusLib::slotModbusStateChange
 * @param state
 * qt modbus 状态变化
 */
void LHModbusLib::slotModbusStateChange( const int& state ) {
    //    qDebug() << "LHModbusLib::slotModbusStateChange:" << state;
    if ( state == 1 ) { myModbus->connectModbus(); }
    emit signalsModbusBack( "state", QModbusDataUnit(), QString( tr( "%1" ).arg( state ) ) );
}
/**
 * @brief LHModbusLib::slotModbusError
 * @param errorInfo
 * qt modbus 发生错误
 */
void LHModbusLib::slotModbusError( const QString& errorInfo ) {
    qDebug() << "LHModbusLib::slotModbusError" << errorInfo;
    isError = true;
    emit signalsModbusBack( "error", QModbusDataUnit(), errorInfo );
}
/**
 * @brief LHModbusLib::slotModbusConnectSucessful
 * qt modbus 连接成功
 */
void LHModbusLib::slotModbusConnectSucessful() {
    //    qDebug() << "LHModbusLib::slotModbusConnectSucessful";
    emit signalsModbusBack( "connect", QModbusDataUnit(), "modbusconnectting" );
}

void LHModbusLib::slotLHModbusInit() {
    myModbus = new MyModbus( this );
    connect( myModbus, &MyModbus::sigModbusReady, this, &LHModbusLib::slotModbusReadBack );
    connect( myModbus, &MyModbus::sigModbusReadError, this, &LHModbusLib::slotModbusError );
    connect( myModbus, &MyModbus::sigModbusWriterError, this, &LHModbusLib::slotModbusError );
    connect( myModbus, &MyModbus::sigModbusConnectError, this, &LHModbusLib::slotModbusError );
    connect( myModbus, &MyModbus::sigModbusStateChanged, this, &LHModbusLib::slotModbusStateChange );
    connect( myModbus, &MyModbus::sigModbusConnectSuccesful, this, &LHModbusLib::slotModbusConnectSucessful );
    myModbus->initModbus();

    //开启定时器，定时读取操作数据
    QTimer* time = new QTimer();
    connect( time, SIGNAL( timeout() ), this, SLOT( sltTimeOut() ) );
    time->start( ParamModbus::SerialFrequency );
}

void LHModbusLib::sltTimeOut() {
    static int  time_read;
    static bool isWriter;
    if ( !isError && writerList && !writerList->isEmpty() && myModbus ) {
        isWriter = true;
        myModbus->onWriterModbus( writerList->takeAt( 0 ) );
    }
    if ( !isError && ( ++time_read >= ( ParamModbus::ModbusHighFrequency / ParamModbus::SerialFrequency ) ) ) { writerList->append( hightFreqenceyUnit ); }
    //根据Modbus.ini配置以ModbsuReadFrequency频率
    if ( !isError && ( ++time_read >= ( ParamModbus::ModbsuReadFrequency / ParamModbus::SerialFrequency ) ) && !isWriter ) {
        onModbusRead();
        time_read = 0;
    }
    isWriter = false;
}
/**
 * @brief LHModbusLib::onModbusRead
 * 读取所有ModbusRead.ini配置的值
 */
void LHModbusLib::onModbusRead() {
    QMap< QString, ModbusRWParam::ModbusIniMode >* readModeMap = ModbusRWParam::getInstance().getAllReadModbusIniMode();
    for ( QString& key : readModeMap->keys() ) {
        ModbusRWParam::ModbusIniMode readMode = readModeMap->value( key );
        QModbusDataUnit              modUnit  = QModbusDataUnit( QModbusDataUnit::RegisterType( readMode.value_type ), readMode.adress, readMode.data_length );
        if ( myModbus ) myModbus->onReadModbus( modUnit );
    }
}

/**
 * @brief LHModbusLib::onInitModbusDataUnit
 * @param name
 * @return 根据名称检测配置文件，如果配置文件未包含，返回带QModbusDataUnit::RegisterType::Invalid请求封装
 */
QModbusDataUnit LHModbusLib::onInitModbusDataUnit( const QString& name ) {
    ModbusRWParam::ModbusIniMode initMode;
    if ( ModbusRWParam::getInstance().getWriterModbusIniMode( name, initMode ) ) {
        return QModbusDataUnit( QModbusDataUnit::RegisterType( initMode.value_type ), initMode.adress, initMode.data_length );
    }
    return QModbusDataUnit( QModbusDataUnit::RegisterType::Invalid, 0, 0 );
}

void LHModbusLib::onConfigWriterString( QModbusDataUnit& writerStringUnit, const QString& data ) {
    QTextCodec* pGBK  = QTextCodec::codecForName( "GB2312" );
    QByteArray  bytes = pGBK->fromUnicode( data );
    int         count = qCeil( float( bytes.size() ) / 2 );
    // qDebug() << "count" << count;
    for ( int i = 0; i < count; i++ ) {
        quint16 value = 0;
        if ( i == count - 1 && 2 * count > bytes.size() ) {
            //奇数处理,添加空格
            value = static_cast< uchar >( bytes[ 2 * i ] + static_cast< uchar >( 32 << 8 ) );
        }
        else {
            value = static_cast< uchar >( bytes[ 2 * i ] ) + ( static_cast< uchar >( bytes[ 2 * i + 1 ] ) << 8 );
        }
        writerStringUnit.setValue( i, value );
    }
}

bool LHModbusLib::onWriterIsSame( const QString& key, const QString& data ) {
    QModbusDataUnit init = onInitModbusDataUnit( key );
    onConfigWriterString( init, data );
    QModbusDataUnit old = writerListCache->value( key );
    return old.values() == init.values();
}

bool LHModbusLib::onWriterIsSame( const QString& key, const int& data ) {
    return writerListCache->value( key ).value( 0 ) == static_cast< quint16 >( data );
}

void LHModbusLib::onConfigWriterListInter( const QString& data, const ModbusRWParam::ModbusListIniMode& initListMode ) {
    QModbusDataUnit stringUnit = QModbusDataUnit( QModbusDataUnit::RegisterType::HoldingRegisters, initListMode.value_adress, initListMode.value_length );
    onConfigWriterString( stringUnit, data );
    writerList->append( stringUnit );
    QModbusDataUnit controlUnit = QModbusDataUnit( QModbusDataUnit::RegisterType::HoldingRegisters, initListMode.control_adress, 1 );
    controlUnit.setValue( 0, initListMode.control_take_value );
    writerList->append( controlUnit );
}

void LHModbusLib::onModbusDisconnect() {
    myModbus->onDisconnct();
}
